//
//  VideoPlayerLayerManager.swift
//  VideoPlayer
//
//  Created by JY_NEW on 2021/10/9.
//

import Foundation
import UIKit
import SnapKit

public class VideoPlayerLayerManager: NSObject, VideoPlayerLayerManagerType, UIGestureRecognizerDelegate {
    /// 播放管理
    public weak var playerManager: VideoPlayerManagerType? {
        didSet {
            self.layersContianerView.removeFromSuperview()
            if let view = self.playerManager?.view {
                view.addSubview(self.layersContianerView)
                self.layersContianerView.snp.makeConstraints { make in
                    make.edges.equalTo(view)
                }
            }
            self.layers.forEach({ $0.playerManager = self.playerManager })
        }
    }
    
    public let observer: VideoPlayerLayerManagerObserverType = VideoPlayerLayerManagerObserver()
  
    /// 当前所有层
    private(set) public var layers: [VideoPlayerLayerType] = []
    /// 所有层都添加在该容器下
    public var layersContianerView = UIView()
    public var isControlLocked: Bool = false {
        didSet {
            self.observer.controlLocked.sendActions(for: self.isControlLocked)
        }
    }
    
    /// 当前手势方向
    private var _dragDirection: UISwipeGestureRecognizer.Direction? = nil
    /// 用来判断滑动方向的阀值
    private let _gestureMinimumTranslation: CGFloat = 20
    
    public override init() {
        super.init()
        self.layersContianerView.clipsToBounds = true
        
        self.bindEvents()
    }
    // MARK: 事件操作
    
    private func bindEvents() {
        self.layersContianerView.isUserInteractionEnabled = true
        
        let singleTap = UITapGestureRecognizer(target: self, action: #selector(self.onSingleTap(_:)))
        singleTap.delegate = self
        singleTap.numberOfTapsRequired = 1
        self.layersContianerView.addGestureRecognizer(singleTap)
        
        let doubleTap = UITapGestureRecognizer(target: self, action: #selector(self.onDoubleTap(_:)))
        doubleTap.delegate = self
        doubleTap.numberOfTapsRequired = 2
        self.layersContianerView.addGestureRecognizer(doubleTap)
        singleTap.require(toFail: doubleTap)
        
        let longPress = UILongPressGestureRecognizer(target: self, action: #selector(self.onLongPress(_:)))
        longPress.delegate = self
        self.layersContianerView.addGestureRecognizer(longPress)
        
        let drag = UIPanGestureRecognizer(target: self, action: #selector(self.onDrag(_:)))
        drag.delegate = self
        self.layersContianerView.addGestureRecognizer(drag)
    }
    public func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldReceive touch: UITouch) -> Bool {
        return touch.view == self.layersContianerView
    }
    @objc private func onSingleTap(_ gr: UITapGestureRecognizer) {
        self.observer.singleTap.sendActions(for: gr)
    }
    @objc private func onDoubleTap(_ gr: UITapGestureRecognizer) {
        self.observer.doubleTap.sendActions(for: gr)
    }
    @objc private func onLongPress(_ gr: UILongPressGestureRecognizer) {
        self.observer.longPress.sendActions(for: gr)
    }
    @objc private func onDrag(_ gr: UIPanGestureRecognizer) {
        let translation = gr.translation(in: gr.view)
        var location = gr.location(in: gr.view)
        var state = gr.state
        var direction = self._dragDirection
        switch gr.state {
        case .began:
            _dragDirection = nil
        case .changed:
            if _dragDirection == nil {
                direction = self.determineDragDirection(translation)
                if direction != nil {
                    self._dragDirection = direction
                    state = .began
                    location = gr.location(ofTouch: 0, in: gr.view)
                }
            }
        case .ended, .cancelled, .failed:
            if _dragDirection != nil {
                _dragDirection = nil
            }
        default: break
        }
        if let direction = direction {
            let offset: CGFloat?
            switch direction {
            case .up: offset = -translation.y
            case .down: offset = translation.y
            case .left: offset = -translation.x
            case .right: offset = translation.x
            default: offset = nil
            }
            if let offset = offset {
                let info = VideoPlayerLayerDragInfo(direction: direction, location: location, offset: offset, state: state)
                self.observer.drag.sendActions(for: info)
            }
        }
    }
    
    private func determineDragDirection(_ translation: CGPoint) -> UISwipeGestureRecognizer.Direction? {
        if abs(translation.x) > _gestureMinimumTranslation {
            let gestureHorizontal: Bool
            if translation.y == 0.0 {
                gestureHorizontal = true
            } else {
                gestureHorizontal = abs(translation.x / translation.y) > 5.0
            }
            if gestureHorizontal {
                return translation.x > 0.0 ? .right : .left
            }
        } else if abs(translation.y) > _gestureMinimumTranslation / 2 {
            let gestureVertical: Bool
            if translation.x == 0.0 {
                gestureVertical = true
            } else {
                gestureVertical = abs(translation.y / translation.x) > 5.0
            }
            if gestureVertical {
                return translation.y > 0.0 ? .down : .up
            }
        }
        return nil
    }
    
    // MARK: 层操作
    
    /// 添加层
    @discardableResult
    public func addLayer(_ layer: VideoPlayerLayerType) -> Int {
        // 排序
        if let levelIndex = self.layers.firstIndex(where: { $0.level.rawValue > layer.level.rawValue }) {
            self.layers.insert(layer, at: levelIndex)
        }else{
            self.layers.append(layer)
        }
        // 初始化变量
        layer.playerManager = self.playerManager
        layer.manager = self
        if let id = layer.identifier {
            return id
        }else{
            let id = makeLayerIdentifier()
            layer.identifier = id
            return id
        }
    }
    /// 移除层
    public func removeLayer(_ identifier: Int) {
        self.layers.removeAll { layer in
            if layer.identifier == identifier {
                layer.playerManager = nil
                layer.manager = nil
                layer.containerView = nil
                return true
            }
            return false
        }
    }
    /// 移除层
    public func removeLayer<LayerType>(for type: LayerType.Type) where LayerType : VideoPlayerLayerType {
        self.layers.removeAll { layer in
            if layer is LayerType {
                layer.playerManager = nil
                layer.identifier = nil
                return true
            }
            return false
        }
    }
    
    /// 激活指定层
    public func activeLayer(_ layer: VideoPlayerLayerType) {
        if layer.status.isShowed { return }
        switch layer.category {
        case .plugin: self.activePluginLayer(layer)
        case .block: self.activeBlockLayer(layer)
        default: self.activeNormalLayer(layer)
        }
    }
    /// 反激活指定层
    public func deactiveLayer(_ layer: VideoPlayerLayerType) {
        if !layer.status.isActived { return }
        switch layer.category {
        case .plugin: self.deactivePluginLayer(layer)
        case .block: self.deactiveBlockLayer(layer)
        default: self.deactiveNormalLayer(layer)
        }
    }
    /// 激活指定插件层
    internal func activePluginLayer(_ layer: VideoPlayerLayerType) {
        // 显示当前层
        self.setLayerStatus(layer, status: .actived(hide: false))
    }
    /// 激活指定遮挡层
    internal func activeBlockLayer(_ layer: VideoPlayerLayerType) {
        // 关闭所有控制层
        self.layers
            .filter({ $0.category == .control && $0.status.isActived })
            .forEach({ self.setLayerStatus($0, status: .deactived)})
        // 其他操作和其他层一样
        self.activeNormalLayer(layer)
    }
    /// 激活指定层
    internal func activeNormalLayer(_ layer: VideoPlayerLayerType) {
        var isLow = true
        for i in 0..<self.layers.count {
            let other = self.layers[i]
            if isLow && other === layer {
                isLow = false
                continue
            }
            if isLow {
                // 隐藏掉低级的层
                if other.level == layer.level && other.status.isShowed {
                    self.setLayerStatus(other, status: .actived(hide: true))
                }
            }else{
                // 若比他高级的层激活着，不管显示不显示都轮到他
                if other.level == layer.level && other.status.isActived {
                    self.setLayerStatus(layer, status: .actived(hide: true))
                    return
                }
            }
        }
        // 显示当前层
        self.setLayerStatus(layer, status: .actived(hide: false))
    }
    /// 反激活指定插件层
    internal func deactivePluginLayer(_ layer: VideoPlayerLayerType) {
        // 隐藏当前层
        self.setLayerStatus(layer, status: .deactived)
    }
    /// 反激活指定遮挡层
    internal func deactiveBlockLayer(_ layer: VideoPlayerLayerType) {
        // 反激活和普通的一样
        self.deactiveNormalLayer(layer)
    }
    /// 反激活指定层
    internal func deactiveNormalLayer(_ layer: VideoPlayerLayerType) {
        if layer.status.isShowed {
            // 找到上一个激活但被隐藏的同一层显示出来
            if let last = self.layers.last(where: {
                $0.level == layer.level &&
                $0.status.isActivedAndHidden
            }) {
                self.setLayerStatus(last, status: .actived(hide: false))
            }
        }
        // 隐藏当前层
        self.setLayerStatus(layer, status: .deactived)
    }
    /// 设置层的激活状态，并执行相应的显示隐藏操作
    internal func setLayerStatus(_ layer: VideoPlayerLayerType, status: VideoPlayerLayerActivationStatus) {
        if layer.status == status { return }
        if status.isShowed != layer.status.isShowed {
            if status.isShowed {
                let container: UIView
                if let c = layer.containerView {
                    container = c
                }else{
                    if layer.isDeactiveForTapBlank {
                        /// 事件层
                        container = TapContainerView(layer: layer)
                    }else{
                        if layer.category == .block {
                            // 遮挡层要挡住后面的操作
                            container = BlockContainerView()
                        }else{
                            //通用层用穿透
                            container = PenetrationContainerView()
                        }
                    }
                    container.tag = layer.level.rawValue
                    layer.containerView = container
                }
                // 找到最后一个跟自己同等级且显示的，把图层插他上面
                if let lastLayer = self.layers.last(where: { $0.level == layer.level && $0.status.isShowed }),
                    let lastView = lastLayer.containerView {
                    self.layersContianerView.insertSubview(container, aboveSubview: lastView)
                // 没有相同的则找到第一个比他大的插在前面
                }else if let idx = self.layersContianerView.subviews.firstIndex(where: { $0.tag > layer.level.rawValue}) {
                    self.layersContianerView.insertSubview(container, at: idx)
                // 都没有则加在最后面
                }else{
                    self.layersContianerView.addSubview(container)
                }
                container.snp.makeConstraints { make in
                    make.edges.equalTo(self.layersContianerView)
                }
                layer.show {
                    
                }
            }else{
                layer.hide { [weak layer] in
                    layer?.containerView?.removeFromSuperview()
                }
            }
        }
        layer.status = status
        self.observer.layerStatus.sendActions(for: layer)
    }
}
extension VideoPlayerLayerManager {
    /// 穿透容器，已做好事件穿透(自身不响应事件，但里面的控件响应事件)
    open class PenetrationContainerView: UIView {
        open override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
            let view = super.hitTest(point, with: event)
            return view == self ? nil : view
        }
    }
    /// 遮挡容器，事件不穿透，就是普通的UIView
    public typealias BlockContainerView = UIView
    /// 绑定背景点击事件的容器
    open class TapContainerView: UIView, UIGestureRecognizerDelegate {
        open weak var playerLayer: VideoPlayerLayerType?
        public init(layer: VideoPlayerLayerType) {
            self.playerLayer = layer
            super.init(frame: .zero)
            let singleTap = UITapGestureRecognizer(target: self, action: #selector(self.onSingleTap(_:)))
            singleTap.delegate = self
            singleTap.numberOfTapsRequired = 1
            self.addGestureRecognizer(singleTap)
        }
        required public init?(coder: NSCoder) {
            fatalError("init(coder:) has not been implemented")
        }
        public func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldReceive touch: UITouch) -> Bool {
            return touch.view == self
        }
        @objc func onSingleTap(_ gr: UITapGestureRecognizer) {
            self.playerLayer?.deactive()
        }
    }
}

// MARK: 自动生成层标识

fileprivate var __video_player_last_auto_layer_identifier = Int.max
///自动生成不重复的暂停标识
public func makeLayerIdentifier() -> Int {
    __video_player_last_auto_layer_identifier -= 1
    return __video_player_last_auto_layer_identifier
}
